package com.apes.sms.systemSetting.service;

import afu.org.checkerframework.checker.oigj.qual.O;
import afu.org.checkerframework.checker.units.qual.A;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.frame.repository.BranchRepository;
import com.apes.scm.masterdata.party.model.Corporate;
import com.apes.scm.masterdata.party.model.Party;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.party.service.PartyService;
import com.apes.scm.rbac.model.*;
import com.apes.scm.rbac.repository.LocalPermitRepository;
import com.apes.scm.rbac.repository.PostRepository;
import com.apes.scm.rbac.repository.RoleRepository;
import com.apes.scm.rbac.repository.UserRepository;
import com.alibaba.fastjson.JSONArray;
import com.apestech.api.condition.ConditionField;
import com.apestech.framework.xml.condition.modul.Account;
import com.apestech.framework.xml.condition.modul.Condition;
import org.apache.commons.collections4.ListUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * Created by lishikun on 2021/11/30 11:43
 */
@Service("accountNumberService")
public class AccountNumberService extends DomainService {

    @Autowired
    UserRepository userRepository;

    @Autowired
    PartyRepository partyRepository;

    public Object findSupplierAccountNumber(SimpleRequest request) {
        Page<Party> partyPage = SpringManager.getBean(PartyService.class).findAllSupplier(newSimpleRequest(request), "corporate", "Supplier");
        List<Map> param = new ArrayList<>();
        for (Party party : partyPage.getContent()) {
            List<String> supplierIds = new ArrayList<>();
            supplierIds.add(String.valueOf(party.getSupplierCode()));
            List<User> allBySupplier = userRepository.findAllBySupplier(supplierIds);
            Map map = (Map)MapUtil.mapped(party);
            map.put("tags",getTag(party));
            List list = new ArrayList();
            for (User user : allBySupplier) {
                Map mapped = (Map)MapUtil.mapped(user);
                List<Role> roles = new ArrayList<>();
                for (Post post : user.getPosts()) {
                    roles.addAll(post.getRoles());
                }
                mapped.put("roles", MapUtil.mapped(roles));
                list.add(mapped);
            }
            map.put("users", MapUtil.mapped(list));
            param.add(map);
        }
        Map row = new HashMap();
        row.put("total", partyPage.getTotalElements());
        row.put("pages", partyPage.getTotalPages());
        row.put("page", partyPage.getNumber());
        row.put("size", partyPage.getSize());
        row.put("elements", partyPage.getNumberOfElements());
        row.put("content", param);
        return row;
    }

    private List getTag(Party party) {
        List listTag = new ArrayList();
        Corporate corporate = party.getCorporate();
        if (corporate == null) return null;
        if (corporate.isInsuranceProvider())
            listTag.add(MapUtil.mapper("name", "保险供应商"));
        if (corporate.isProductProvider())
            listTag.add(MapUtil.mapper("name", "商品供应商应商"));
        if (corporate.isServiceProvider())
            listTag.add(MapUtil.mapper("name", "服务供应商"));
        if (corporate.isPayProvider())
            listTag.add(MapUtil.mapper("name", "支付供应商"));
        if (corporate.isLogisticsProvider())
            listTag.add(MapUtil.mapper("name", "物流供应商"));
        if (corporate.isStorageProvider())
            listTag.add(MapUtil.mapper("name", "仓储供应商"));
        if (corporate.isUrgentProvider())
            listTag.add(MapUtil.mapper("name", "急件供应商标"));
        if (corporate.isAfterSaleProvider())
            listTag.add(MapUtil.mapper("name", "售后供应商"));
        if (corporate.isInnerProvider())
            listTag.add(MapUtil.mapper("name", "内部供应商"));
        return listTag;

    }

    private SimpleRequest newSimpleRequest(SimpleRequest request) {
        SimpleRequest simpleRequest = new SimpleRequest();
        String ids = null;
        JSONArray condition = request.getJO().getJSONArray("condition");
        Filter authFilter = new Filter();
        Group authGroup = new Group();
        for (int i = 0; i < condition.size(); i++) {
            if ("ids".equals(condition.getJSONObject(i).getString("field"))) {
                ids = condition.getJSONObject(i).getString("value");
            }
            if ("partyRoles.id".equals(condition.getJSONObject(i).getString("field"))) {
                authFilter.setField(condition.getJSONObject(i).getString("field"));
                authFilter.setValue(condition.getJSONObject(i).get("value"));
                authFilter.setOperator(condition.getJSONObject(i).getString("operator"));
                authGroup.addFilter(authFilter);
            }
        }
        Group group = new Group();
        List<Group> groups = new ArrayList<>();

        if (ids != null) {
            List<Filter> filters = new ArrayList<>();
            Filter filter = new Filter();
            filter.setField("partyRoles.id");
            filter.setOperator("EQ");
            filter.setValue(ids);
            filters.add(filter);
            filter = new Filter();
            filter.setField("name");
            filter.setOperator("LIKE");
            filter.setValue(ids);
            filters.add(filter);
            filter = new Filter();
            filter.setField("abbreviation");
            filter.setOperator("LIKE");
            filter.setValue(ids);
            filters.add(filter);
            group.setOperator("or");
            group.setFilters(filters);
            groups.add(group);
            group = new Group();
        }
        if (authGroup.getFilters().size() != 0)
            groups.add(authGroup);
        if (groups.size() != 0)
            group.setGroups(groups);
        JSONObject json = (JSONObject)JSONObject.toJSON(group);
        json.put("size", request.get("size"));
        json.put("page", request.get("page"));
        simpleRequest.setData(json);

        return simpleRequest;
    }

    /**
     * 创建账号
     * @return
     */
    public Object create(SimpleRequest request) {
        JSONObject jo = request.getJO();
        JSONObject model = jo.getJSONObject("model");
        String supplierId = model.getString("supplierCode");
        if (supplierId == null) throw new RuntimeException("");
        LocalPermit localPermit = checkLocalPermit(model);
        List<Post> posts = checkPost(jo, localPermit);
        List<Post> post1 = new ArrayList<>();
        for (Post post : posts) {
            Post newPost = new Post();
            newPost.setId(post.getId());
            newPost.setName(post.getName());
            post1.add(newPost);
        }
        User user = jo.getObject("result", User.class);
        user.setPosts(post1);
        if (user.getId() == null)
            user.setOrigin(getUserOrigin(model));
        setPostLits(user);
        user = (User)invoke("aut.user.save", MapUtil.mapped(user));
        return responseData(model);
    }



    /**
     * 检测本地权限
     */
    private LocalPermit checkLocalPermit(JSONObject model) {
        String supplierId = model.getString("supplierCode");
        List<LocalPermit> localPermits = SpringManager.getBean(LocalPermitRepository.class).findByTypeAndOrgId(supplierId, "0022");
        if (localPermits == null || localPermits.size() == 0) {
            return createLocalPermit(model);
        }
        return localPermits.get(0);
    }

    /**
     * 检测本地角色
     * @param model
     */
    private List<Post> checkPost(JSONObject model, LocalPermit localPermit) {
        JSONArray roles = model.getJSONObject("result").getJSONArray("roles");
        for (int i = 0; i < roles.size(); i++) {
            List<Post> posts = SpringManager.getBean(PostRepository.class).findByLocalPermitIdAndRoleId(localPermit.getId(), roles.getJSONObject(i).getString("id"));
            if (posts == null || posts.size() == 0)
                createPost(model, localPermit, roles.getJSONObject(i));
        }
        List<String> id = new ArrayList<>();
        if (roles.size() == 0) {
            id.add("zzz");
        } else id = roles.stream().map(o -> ((JSONObject) o).getString("id")).collect(Collectors.toList());
        return SpringManager.getBean(PostRepository.class).findByLocalPermitIdAndRoleIds(localPermit.getId(), id);

    }

    private void createPost(JSONObject model, LocalPermit localPermit, JSONObject role) {
        Set<Role> roleList = new HashSet<>();
        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne("0022");
        Post post = new Post();
        post.setName(role.getString("name"));
        post.setLocalPermit(localPermit);
        post.setCompany(company);
        post.setBranch(SpringManager.getBean(BranchRepository.class).findOne("00000241"));
        JSONArray array = model.getJSONObject("result").getJSONArray("roles");
        Role roleById = SpringManager.getBean(RoleRepository.class).findOne(role.getString("id"));
        roleList.add(roleById);
        post.setRoles(roleList);
        SpringManager.getBean(PostRepository.class).saveAndFlush(post);
        }




    /**
     * 创建本地权限
     * @param model
     */
    private LocalPermit createLocalPermit(JSONObject model) {
        PartyRole supplier = SpringManager.getBean(PartyRoleRepository.class).findOne(model.getString("supplierCode"));
        LocalPermit localPermit = new LocalPermit();
        localPermit.setName(supplier.getName());
        Set<LocalPermitItem> localPermitItems = new HashSet<>();
        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne("0022");
        setLocalPermitItems(localPermitItems, "pp_belong", "pt_company", company.getId(), company.getName());
        setLocalPermitItems(localPermitItems, "pp_belong", "pt_supplier", supplier.getId(), supplier.getName());
        setLocalPermitItems(localPermitItems, "pp_search", "pt_company", company.getId(), company.getName());
        setLocalPermitItems(localPermitItems, "pp_search", "pt_supplier", supplier.getId(), supplier.getName());
        setLocalPermitItems(localPermitItems, "pp_operate", "pt_company", company.getId(), company.getName());
        setLocalPermitItems(localPermitItems, "pp_operate", "pt_supplier", supplier.getId(), supplier.getName());
        localPermit.setLocalPermitItems(localPermitItems);
       return SpringManager.getBean(LocalPermitRepository.class).saveAndFlush(localPermit);
    }

    /**
     * 设置明细
     * @param localPermitItems
     * @param purpose
     * @param type
     * @param orgId
     * @param orgName
     */
    private void setLocalPermitItems(Set<LocalPermitItem> localPermitItems, String purpose, String type, String orgId, String orgName) {
        LocalPermitItem localPermitItem = new LocalPermitItem();
        Enumeration typeEnumeration = new Enumeration();
        Enumeration purposeEnumeration = new Enumeration();
        typeEnumeration.setId(type);
        purposeEnumeration.setId(purpose);
        localPermitItem.setPurpose(purposeEnumeration);
        localPermitItem.setType(typeEnumeration);
        localPermitItem.setOrgId(orgId);
        localPermitItem.setOrgName(orgName);
        localPermitItems.add(localPermitItem);
    }


    private String getUserOrigin(JSONObject model) {
        int index = model.getJSONArray("users") != null ? model.getJSONArray("users").size() + 1 : 1;
        String supplierId = model.getString("supplierCode");
        String userOrigin = "";
        if (supplierId.indexOf("G") != 0 ) userOrigin += "G";
        userOrigin += supplierId + String.format("%02d", index);
        return  userOrigin;
    }

    private void setPostLits(User user) {
        List<Post> posts = user.getPosts();
        List<JSONObject> jsonObjects = new ArrayList<>();
        for (Post post : posts) {
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(post));
            jsonObjects.add(jsonObject);
        }
        user.setPostLits(jsonObjects);
    }

    private Map responseData(JSONObject model) {
        List<String> supplierIds = new ArrayList<>();
        supplierIds.add(model.getString("supplierCode"));
        List<User> allBySupplier = userRepository.findAllBySupplier(supplierIds);
        Party party = partyRepository.findOne(model.getLongValue("id"));
        SpringManager.getBean(PartyService.class).roleCodeFormat(party);
        Map map = (Map)MapUtil.mapped(party);
        map.put("tags",getTag(party));
        List list = new ArrayList();
        List<Role> roles = new ArrayList<>();
        for (User user : allBySupplier) {
            roles = new ArrayList<>();
            Map mapped = (Map)MapUtil.mapped(user);
            for (Post post : user.getPosts()) {
                roles.addAll(post.getRoles());
            }
            mapped.put("roles", MapUtil.mapped(roles));
            list.add(mapped);
            roles.clear();
        }
        map.put("users", list);
        return map;
    }


    /**
     * 重置密码
     */
    public Map resetPassword(SimpleRequest request) {
        User user = request.getJO().getObject("result", User.class);
        User SystemUser = userRepository.findByOrigin(user.getOrigin());
        if (SystemUser.getVersion() != user.getVersion()) throw new RuntimeException("记录已更新或已删除，请重新提交！[乐观锁]");
        user.setPassword("e10adc3949ba59abbe56e057f20f883e");
        setPostLits(user);
        invoke("aut.user.save", MapUtil.mapped(user));
        return responseData(request.getJO().getJSONObject("model"));
    }

    /**
     * 禁用供应商账号
     * @param request
     * @return
     */
    public Map disableAccountNumber(SimpleRequest request) {
        User user = request.getJO().getObject("result", User.class);
        User SystemUser = userRepository.findByOrigin(user.getOrigin());
        if (SystemUser.getVersion() != user.getVersion()) throw new RuntimeException("记录已更新或已删除，请重新提交！[乐观锁]");
        SystemUser.setDisable(true);
        userRepository.saveAndFlush(SystemUser);
        return responseData(request.getJO().getJSONObject("model"));
    }

    /**
     * 启动供应商账号
     * @param request
     * @return
     */
    public Map start(SimpleRequest request) {
        User user = request.getJO().getObject("result", User.class);
        User SystemUser = userRepository.findByOrigin(user.getOrigin());
        if (SystemUser.getVersion() != user.getVersion()) throw new RuntimeException("记录已更新或已删除，请重新提交！[乐观锁]");
        SystemUser.setDisable(false);
        userRepository.saveAndFlush(SystemUser);
        return responseData(request.getJO().getJSONObject("model"));
    }




    public boolean equalList(List list1, List list2) {
        if (list1.size() != list2.size())
            return false;
        for (Object object : list1) {
            if (!list2.contains(object))
                return false;
        }
        return true;
    }
}
